#ifndef ILI9325FSMC_H
#define ILI9325FSMC_H

#include "stm32f4xx.h"
#include "bitops.h"
#include "utils.h"

#define RST PFO(1)

#define BUS_8_BIT

#ifdef BUS_8_BIT
typedef struct {
    __IO u8 IR;
    __IO u8 REG;
} ILI9325TypeDef;

#define ILI9325_ADDR_BASE ((u32)0x60000000)
#define ILI9325 ((ILI9325TypeDef *)ILI9325_ADDR_BASE)

typedef enum {
    RED = 0xF800,
    GREEN = 0x07E0,
    BLUE = 0x001F,
    WHITE = 0xFFFF,
    BLACK = 0x0000
} Color;

typedef enum {
    FRONT_SIZE_12 = 12,
    FRONT_SIZE_16 = 16
} FrontSize;

#else
typedef struct {
    __IO u16 IR;
    __IO u16 REG;
} ILI9325TypeDef;

#define ILI9325_ADDR_BASE ((u32)0x60000000)
#define ILI9325 ((ILI9325TypeDef *)ILI9325_ADDR_BASE)

#endif

#ifdef BUS_8_BIT
#define WriteIR(index) \
{ \
    ILI9325->IR = (u16)index >> 8; \
    ILI9325->IR = (u16)index & 0x00ff; \
}

#define WriteREG(data) \
{ \
    ILI9325->REG = (u16)data >> 8; \
    ILI9325->REG = (u16)data & 0x00ff; \
}


#define WriteIRReg(index, data) \
{ \
    WriteIR(index); \
    WriteREG(data); \
}

#define ReadREG(data) \
{ \
    data = (u16)ILI9325->REG << 8; \
    data |= ILI9325->REG; \
}

#define ReadIRReg(index, data) \
{ \
    WriteIR(index); \
    ReadREG(data); \
}

#else

#define WriteIR(index) \
{ \
    ILI9325->IR = index; \
}

#define WriteREG(data) \
{ \
    ILI9325->REG = (u16)data; \
}

#define WriteIRReg(index, data) \
{ \
    WriteIR(index); \
    WriteREG(data); \
}

#define ReadREG(data) \
{ \
    data = (u16)ILI9325->REG; \
}

#define ReadIRReg(index, data) \
{ \
    WriteIR(index); \
    ReadREG(data); \
}

#endif

void ILI9325Init(void);
void ILI9325Clear(u16 color);
void ILI9325SetFrontColor(Color frontC);
void ILI9325SetBackColor(Color backC);
void ILI9325DrawPoint(u16 x,u16 y, Color color);
Color ILI9325GetPoint(u16 x, u16 y);
void ILI9325DrawLine(u16 x1, u16 y1, u16 x2, u16 y2);
void ILI9325DrawCircle(u16 x0,u16 y0,u8 r);
void ILI9325PutStr(u32 x,u32 y,u8 *str,
                 u16 dcolor,u16 bgcolor);
void ILI9325Printf(u16 x, u16 y, u16 width, u16 height,
                   FrontSize size, u8 mode, char *fmt, ...);
u16 ILI9325GetWidth(void);
u16 ILI9325GetHeight(void);
void ILI9325SetWinArea(u16 x1, u16 y1,
                 u16 x2, u16 y2);
void ILI9325SetCursor(u16 x, u16 y);

#endif // ILI9325FSMC_H
